package com.stars.easyms.base.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintWriter;
import java.io.StringWriter;

/***
 * 异常信息处理工具类
 *
 * @author guoguifang
 * @date 2018-10-19 10:07
 * @since 1.0.0
 */
public final class ExceptionUtil {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionUtil.class);

    public static String getThowableTrace(Throwable throwable) {
        try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
            throwable.printStackTrace(pw);
            return sw.toString();
        } catch (Exception e) {
            logger.error("异常栈信息获取失败:", e);
        }
        return null;
    }

    public static Throwable extractThrowable(Object... argArray) {
        int arrLength;
        if (argArray == null || (arrLength = argArray.length) == 0) {
            return null;
        }
        final Object lastEntry = argArray[arrLength - 1];
        if (lastEntry instanceof Throwable) {
            return (Throwable) lastEntry;
        }
        return null;
    }

    public static Object[] extractNonThrowable(Object... argArray) {
        int arrLength;
        if (argArray == null || (arrLength = argArray.length) == 0) {
            return argArray;
        }
        final int trimemdLen = arrLength - 1;
        Object[] trimmed = new Object[trimemdLen];
        System.arraycopy(argArray, 0, trimmed, 0, trimemdLen);
        return trimmed;
    }

    public static Object[] trimmedCopy(Object... argArray) {
        int arrLength;
        if (argArray == null || (arrLength = argArray.length) == 0) {
            return argArray;
        }
        if (!(argArray[arrLength - 1] instanceof Throwable)) {
            return argArray;
        }
        final int trimemdLen = arrLength - 1;
        Object[] trimmed = new Object[trimemdLen];
        System.arraycopy(argArray, 0, trimmed, 0, trimemdLen);
        return trimmed;
    }

    /**
     * 根据异常获取错误描述信息
     *
     * @param ex 异常信息
     * @return 错误信息
     */
    public static String getExceptionDesc(Throwable ex) {
        String errorDesc;
        Throwable throwable = getNestedThrowable(ex);
        if (throwable instanceof NullPointerException) {
            errorDesc = NullPointerException.class.getName();
        } else {
            errorDesc = throwable.getMessage();
        }
        if (errorDesc != null && errorDesc.length() > 200) {
            errorDesc = errorDesc.substring(0, 200);
        }
        return errorDesc;
    }

    /**
     * 获取首行的异常栈信息
     *
     * @param th 异常
     * @return 异常栈信息
     */
    public static String getFirstExceptionStack(Throwable th) {
        Throwable throwable = getNestedThrowable(th);
        StackTraceElement[] stackTraces = throwable.getStackTrace();
        if (stackTraces.length > 0) {
            return stackTraces[0].toString();
        }
        return "";
    }

    /**
     * 获取嵌套内的异常
     *
     * @param th 异常
     * @return 嵌套内的异常
     */
    public static Throwable getNestedThrowable(Throwable th) {
        Throwable throwable = th;
        int nestedIndex = 0;
        while (throwable.getCause() != null && throwable.getCause() != throwable && nestedIndex++ < 5) {
            throwable = throwable.getCause();
        }
        return throwable;
    }

    private ExceptionUtil() {
    }
}
